﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Red.GameData;
using System.Drawing;
using GameDataTempshitEditor.Widgets;

namespace GameDataTempshitEditor.DataEditors
{
    /// <summary>
    /// Root item representing the object view
    /// </summary>
    public class GameData_PropertyGroup_Root : Widgets.PropertyGroupBase
    {
        public GameData_PropertyGroup_Root(PropertyItemBase parent, EditorContext context, EditorObjectView view, bool canEdit)
            : base(parent, view.DisplayName)
        {
            _CanEdit = canEdit;
            _Context = context;
            _LastPropertyCount = -1;
            _View = view;
            Expand();
        }

        public override RefreshResult RefreshThis()
        {
            var showAdvancedProps = Settings.ShowAdvancedProperties;

            // determine if the way we show properties changed
            {
                int numDisplayableProperties = 0;

                // count visible properties
                foreach (var prop in _View.Properties)
                    if (showAdvancedProps || !prop.IsAdvanced)
                        numDisplayableProperties += 1;

                // the number of properties that should be displayed have changed, recycle the view
                if (numDisplayableProperties != _LastPropertyCount)
                {
                    _LastPropertyCount = numDisplayableProperties;
                    Collapse();
                    Expand();

                    return RefreshResult.TreeRefreshed;
                }
            }

            // by default we have nothing to refresh here
            return RefreshResult.NoRefresh;
        }

        public override Brush GetBackgroundBrush(DataPropertyGridDrawStyle style, bool isSelected)
        {
            if (!isSelected)
                return style.BackgroundBrushGroup;

            return base.GetBackgroundBrush(style, isSelected);
        }

        public override bool ExpandElement(ref List<PropertyItemBase> newElements)
        {
            var showAdvancedProps = Settings.ShowAdvancedProperties;

            var groups = new CategoryGrouping();
            groups.AddObject(_View, showAdvancedProps);

            // create groups per category
            foreach (var category in groups.Categories)
            {
                newElements.Add(new GameData_PropertyGroup_Category(this, _Context, category.Name, category.Props, _CanEdit));            
            }

            _LastPropertyCount = groups.PropertyCount;
            return true;
        }

        public readonly EditorObjectView _View;
        public readonly EditorContext _Context;

        private bool _CanEdit;
        private int _LastPropertyCount;
    }

    /// <summary>
    /// Internal helper class used to group properties by category
    /// </summary>
    class CategoryGrouping
    {
        public class Category
        {
            public string Name;
            public List<EditorPropertyView> Props;

            public Category(string _name)
            {
                Name = _name;
                Props = new List<EditorPropertyView>();
            }
        }

        public List<Category> Categories;
        public int PropertyCount;

        public CategoryGrouping()
        {
            Categories = new List<Category>();
            PropertyCount = 0;
        }

        private Category FindCategory(string name)
        {
            foreach (var cat in Categories)
                if (cat.Name == name)
                    return cat;

            var newCat = new Category(name);
            Categories.Add(newCat);
            return newCat;
        }

        public void AddProp(EditorPropertyView prop)
        {
            // find category
            var cat = FindCategory(prop.Category);
            cat.Props.Add(prop);

            PropertyCount += 1;
        }

        public void AddObject(EditorObjectView view, bool showAdvancedProperties)
        {
            foreach (var prop in view.Properties)
            {
                if (prop.IsAdvanced && !showAdvancedProperties)
                    continue;

                AddProp(prop);
            }
        }
    }

}
